// scoped_allocator standard header
#ifndef _SCOPED_ALLOCATOR_
#define _SCOPED_ALLOCATOR_
#include <tuple>
#include <xmemory0>

_STD_BEGIN
 #if _HAS_VARIADIC_TEMPLATES
template<class _Outer,
	class... _Inner>
	class scoped_allocator_adaptor;

		// TEMPLATE STRUCT _Scoped_propagate_on_container_copy

 #if 0 < __GNUC__	/* compiler test */
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_copy
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_copy_assignment
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(int)
			-> typename allocator_traits<_Xouter>
				::propagate_on_container_copy_assignment;
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(_Wrap_int)
			-> _If<allocator_traits<_Xouter>
				::propagate_on_container_copy_assignment::value,
				true_type,
				decltype(_Fn<_Xinner...>())>;

	typedef decltype(_Fn<_Outer, _Inner...>(0)) type;
	};

 #else /* 0 < __GNUC__ */

template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_copy
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_copy_assignment
	typedef typename _If<allocator_traits<_Outer>
		::propagate_on_container_copy_assignment::value,
		true_type,
		_Scoped_propagate_on_container_copy<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_copy<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_copy_assignment
	typedef typename allocator_traits<_Outer>
		::propagate_on_container_copy_assignment::type type;
	};
 #endif /* 0 < __GNUC__ */

		// TEMPLATE STRUCT _Scoped_propagate_on_container_move

 #if 0 < __GNUC__	/* compiler test */
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_move
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_move_assignment
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(int)
			-> typename allocator_traits<_Xouter>
				::propagate_on_container_move_assignment;
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(_Wrap_int)
			-> _If<allocator_traits<_Xouter>
				::propagate_on_container_move_assignment::value,
				true_type,
				decltype(_Fn<_Xinner...>())>;

	typedef decltype(_Fn<_Outer, _Inner...>(0)) type;
	};

 #else /* 0 < __GNUC__ */
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_move
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_move_assignment
	typedef typename _If<allocator_traits<_Outer>
		::propagate_on_container_move_assignment::value,
		true_type,
		_Scoped_propagate_on_container_move<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_move<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_move_assignment
	typedef typename allocator_traits<_Outer>
		::propagate_on_container_move_assignment::type type;
	};
 #endif /* 0 < __GNUC__ */

		// TEMPLATE STRUCT _Scoped_propagate_on_container_swap

 #if 0 < __GNUC__	/* compiler test */
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_swap
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_swap
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(int)
			-> typename allocator_traits<_Xouter>
				::propagate_on_container_swap;
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(_Wrap_int)
			-> _If<allocator_traits<_Xouter>
				::propagate_on_container_swap::value,
				true_type,
				decltype(_Fn<_Xinner...>())>;

	typedef decltype(_Fn<_Outer, _Inner...>(0)) type;
	};

 #else /* 0 < __GNUC__ */
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_swap
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_swap
	typedef typename _If<allocator_traits<_Outer>
		::propagate_on_container_swap::value,
		true_type,
		_Scoped_propagate_on_container_swap<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_swap<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_swap
	typedef typename allocator_traits<_Outer>
		::propagate_on_container_swap::type type;
	};
 #endif /* 0 < __GNUC__ */

		// TEMPLATE STRUCT _Scoped_is_always_equal

 #if 0 < __GNUC__	/* compiler test */
template<class _Outer,
	class... _Inner>
	struct _Scoped_is_always_equal
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::is_always_equal
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(int)
			-> typename allocator_traits<_Xouter>
				::is_always_equal;
	template<class _Xouter,
		class... _Xinner>
		static auto _Fn(_Wrap_int)
			-> _If<!allocator_traits<_Xouter>
				::is_always_equal::value,
				false_type,
				decltype(_Fn<_Xinner...>())>;

	typedef decltype(_Fn<_Outer, _Inner...>(0)) type;
	};

 #else /* 0 < __GNUC__ */

template<class _Outer,
	class... _Inner>
	struct _Scoped_is_always_equal
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::is_always_equal
	typedef typename _If<!allocator_traits<_Outer>
		::is_always_equal::value,
		false_type,
		_Scoped_is_always_equal<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_is_always_equal<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::is_always_equal
	typedef typename allocator_traits<_Outer>
		::is_always_equal::type type;
	};
 #endif /* 0 < __GNUC__ */

		// TEMPLATE STRUCT _Scoped_outermost_allocator
template<class _Outer>
	struct _Scoped_outermost_allocator
	{	// chooses outermost x.outer_allocator() or x
	template<class _Xouter>
		static auto _Fn(int, _Xouter& _Alval)
			-> decltype(_Alval.outer_allocator())
		{	// returned nested allocator argument
		return (_Alval.outer_allocator());
		}

	template<class _Xouter>
		static auto _Fn(_Wrap_int, _Xouter& _Alval)
			-> _Xouter&
		{	// returned allocator argument
		return (_Alval);
		}

	static _Outer _Outer_obj;

	typedef typename remove_reference<
		decltype(_Fn<_Outer>(0, _Outer_obj))>::type type;
	};

		// TEMPLATE FUNCTION _Scoped_construct
template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types,
	class _Dont_care>
	void _Scoped_construct(_Outermost, _Inner,
		false_type, _Dont_care,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, no allocator
	::new (static_cast<void *>(_Ptr)) _Ty(_STD forward<_Types>(_Args)...);
	}

template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types>
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval,
		true_type, false_type,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, leading allocator
	allocator_traits<_Outermost>::construct(_Alval, _Ptr,
		allocator_arg, _Inner_alval,
			_STD forward<_Types>(_Args)...);
	}

template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types>
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval,
		true_type, true_type,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, trailing allocator
	allocator_traits<_Outermost>::construct(_Alval, _Ptr,
		_STD forward<_Types>(_Args)...,
			_Inner_alval);
	}

		// TEMPLATE FUNCTION _Scoped_construct_tuple
template<class _Alloc,
	class _Ty,
	class... _Atypes,
	class _Dont_care>
	tuple<_Atypes...>
		_Scoped_construct_tuple(_Alloc&, false_type, _Dont_care,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, no allocator
	return (_Val);
	}

template<class _Alloc,
	class _Ty,
	class... _Atypes>
	tuple<allocator_arg_t, _Alloc&, _Atypes...>
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, false_type,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, leading allocator
	return (tuple_cat(tuple<allocator_arg_t, _Alloc&>(
		_Tuple_alloc, _Alty), _Val));
	}

template<class _Alloc,
	class _Ty,
	class... _Atypes>
	tuple<_Atypes..., _Alloc&>
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, true_type,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, trailing allocator
	return (tuple_cat(_Val,
		tuple<_Alloc&>(_Alty)));
	}

		// TEMPLATE FUNCTION _Scoped_construct_pair
template<class _Inner,
	class _Ty1,
	class _Ty2,
	class... _Uy1,
	class... _Uy2>
	void _Scoped_construct_pair(_Inner _Inner_alval,
		pair<_Ty1, _Ty2> *_Ptr,
		tuple<_Uy1...> _Val1, tuple<_Uy2...> _Val2)
	{	// construct pair from tuples
	::new (static_cast<void *>(_Ptr)) pair<_Ty1, _Ty2>(piecewise_construct,
		_Scoped_construct_tuple<_Inner, _Ty1, _Uy1...>(
			_Inner_alval,
			uses_allocator<_Ty1, _Inner>(),
			is_constructible<_Ty1, _Uy1..., _Inner>(),
			_Val1),
		_Scoped_construct_tuple<_Inner, _Ty2, _Uy2...>(
			_Inner_alval,
			uses_allocator<_Ty2, _Inner>(),
			is_constructible<_Ty2, _Uy2..., _Inner>(),
			_Val2));
	}

		// TEMPLATE CLASS _Scoped_base
template<class _Outer,
	class... _Inner>
	struct _Scoped_base;

template<class _Outer,
	class _Inner0,
	class... _Inner>
	struct _Scoped_base<_Outer, _Inner0, _Inner...>
		: public _Outer
	{	// nest of allocators, arbitrary depth
	typedef scoped_allocator_adaptor<_Outer, _Inner0, _Inner...>
		_Myadaptor;
	typedef scoped_allocator_adaptor<_Inner0, _Inner...>
		inner_allocator_type;

	inner_allocator_type _Inner_obj;

	inner_allocator_type& _Get_inner_object(
		_Myadaptor&)
		{	// return _Inner_obj as inner_object
		return (_Inner_obj);
		}

	const inner_allocator_type& _Get_inner_object(
		const _Myadaptor&) const
		{	// return _Inner_obj as inner_object
		return (_Inner_obj);
		}

	_Scoped_base()
		{	// default construct
		}

	template<class _Other1,
		class _Other2>
		_Scoped_base(_Other1&& _Outer_arg,
			_Other2&& _Inner_arg)
		: _Inner_obj(_STD forward<_Other2>(_Inner_arg))
		{	// construct from (outer, inner)
		(_Outer&)*this = _STD forward<_Other1>(_Outer_arg);
		}

	template<class _Other>
		void operator=(
			scoped_allocator_adaptor<_Other, _Inner0, _Inner...>&&
				_Right)
		{	// move from adaptor<_Other, _Inner0, _Inner...>
		(_Outer&)*this = _STD forward<_Other>(_Right);
		_Inner_obj = _STD forward<inner_allocator_type>(_Right._Inner_obj);
		}

	template<class _Other>
		void operator=(
			const scoped_allocator_adaptor<_Other, _Inner0, _Inner...>&
				_Right)
		{	// assign from adaptor<_Other, _Inner0, _Inner...>
		(_Outer&)*this = (_Other&)_Right;
		_Inner_obj = _Right._Inner_obj;
		}

	_Myadaptor select_on_container_copy_construction() const
		{	// make new adaptor
		return (_Myadaptor(allocator_traits<_Outer>
			::select_on_container_copy_construction(*this),
			_Inner_obj.select_on_container_copy_construction()));
		}
	};

template<class _Outer>
	struct _Scoped_base<_Outer>
		: public _Outer
	{	// nest of allocators, one deep
	typedef scoped_allocator_adaptor<_Outer> _Myadaptor;
	typedef scoped_allocator_adaptor<_Outer> inner_allocator_type;

	inner_allocator_type& _Get_inner_object(
		_Myadaptor& _Self)
		{	// return self as inner_object
		return (_Self);
		}

	const inner_allocator_type& _Get_inner_object(
		const _Myadaptor& _Self) const
		{	// return self as inner_object
		return (_Self);
		}

	_Scoped_base()
		{	// default construct
		}

	template<class _Other1,
		class _Other2>
		_Scoped_base(_Other1&& _Outer_arg,
			_Other2&&)
		: _Outer(_STD forward<_Other1>(_Outer_arg))
		{	// construct from (outer, inner)
		}

	template<class _Other>
		void operator=(scoped_allocator_adaptor<_Other>&& _Right)
		{	// move from adaptor<_Other>
		(_Outer&)*this = _STD forward<_Other>((_Other&)_Right);
		}

	template<class _Other>
		void operator=(const scoped_allocator_adaptor<_Other>& _Right)
		{	// assign from adaptor<_Other>
		(_Outer&)*this = (_Other&)_Right;
		}

	_Myadaptor select_on_container_copy_construction() const
		{	// make new adaptor
		return (_Myadaptor(allocator_traits<_Outer>
			::select_on_container_copy_construction(*this)));
		}
	};

		// TEMPLATE CLASS scoped_allocator_adaptor
template<class _Outer,
	class... _Inner>
	class scoped_allocator_adaptor
		: public _Scoped_base<_Outer, _Inner...>
	{	// nest of allocators
	typedef _Scoped_base<_Outer, _Inner...> _Mybase;
	typedef allocator_traits<_Outer> _Outer_traits;
	typedef typename _Scoped_outermost_allocator<_Outer>::type _Outermost;
	typedef allocator_traits<_Outermost> _Outermost_traits;

public:
	typedef _Outer outer_allocator_type;
	typedef typename _Mybase::inner_allocator_type inner_allocator_type;

	typedef typename _Outer_traits::value_type value_type;
	typedef typename _Outer_traits::pointer pointer;
	typedef typename _Outer_traits::const_pointer const_pointer;
	typedef typename _Outer_traits::void_pointer void_pointer;
	typedef typename _Outer_traits::const_void_pointer const_void_pointer;

	typedef typename _Outer_traits::size_type size_type;
	typedef typename _Outer_traits::difference_type difference_type;

	template<class _Other>
		struct rebind
		{	// converts X<value_type> to X<_Other>
		typedef typename _Get_rebind_type<_Outer, _Other>::type _Other_alloc;
		typedef scoped_allocator_adaptor<_Other_alloc, _Inner...> other;
		};

	typedef typename
		_Scoped_propagate_on_container_copy<_Outermost, _Inner...>::type
			propagate_on_container_copy_assignment;
	typedef typename
		_Scoped_propagate_on_container_move<_Outermost, _Inner...>::type
			propagate_on_container_move_assignment;
	typedef typename
		_Scoped_propagate_on_container_swap<_Outermost, _Inner...>::type
			propagate_on_container_swap;

	typedef typename
		_Scoped_is_always_equal<_Outermost, _Inner...>::type
			is_always_equal;

	outer_allocator_type& outer_allocator() _NOEXCEPT
		{	// get reference to outer allocator
		return (static_cast<_Outer&>(*this));
		}

	const outer_allocator_type& outer_allocator() const _NOEXCEPT
		{	// get reference to outer allocator
		return (static_cast<const _Outer&>(*this));
		}

	inner_allocator_type& inner_allocator() _NOEXCEPT
		{	// get reference to inner allocator
		return (const_cast<inner_allocator_type&>(
			this->_Get_inner_object(*this)));
		}

	const inner_allocator_type& inner_allocator() const _NOEXCEPT
		{	// get reference to inner allocator
		return (this->_Get_inner_object(*this));
		}

	scoped_allocator_adaptor()
		{	// default construct
		}

	scoped_allocator_adaptor(const scoped_allocator_adaptor& _Right) _NOEXCEPT
		: _Mybase(_Right.outer_allocator(),
			_Right.inner_allocator())
		{	// construct from _Right
		}

	template<class _Other>
		scoped_allocator_adaptor(_Other&& _Other_arg,
			const _Inner&... _Inner_arg) _NOEXCEPT
		: _Mybase(_STD forward<_Other>(_Other_arg),
			_STD forward<inner_allocator_type>(
				inner_allocator_type(_Inner_arg...)))
		{	// construct from (_Other, _Inner...)
		}

	template<class _Other>
		scoped_allocator_adaptor(const scoped_allocator_adaptor<_Other,
			_Inner...>& _Right) _NOEXCEPT
		: _Mybase(_Right.outer_allocator(),
			_Right.inner_allocator())
		{	// construct from const adaptor<_Other, _Inner...>&
		}

	template<class _Other>
		scoped_allocator_adaptor(scoped_allocator_adaptor<_Other,
			_Inner...>&& _Right) _NOEXCEPT
		: _Mybase(_STD forward<_Other>(_Right.outer_allocator()),
			_Right.inner_allocator())
		{	// construct from adaptor<_Other, _Inner...>&&
		}

	template<class _Other>
		scoped_allocator_adaptor& operator=(
			scoped_allocator_adaptor<_Other, _Inner...>&& _Right)
		{	// assign from adaptor<_Other, _Inner...>&&
		_Mybase::operator=(_STD forward<_Other>(_Right));
		return (*this);
		}

	template<class _Other>
		scoped_allocator_adaptor& operator=(
			const scoped_allocator_adaptor<_Other, _Inner...>& _Right)
		{	// assign from adaptor<_Other, _Inner...>&
		_Mybase::operator=(_Right);
		return (*this);
		}

	pointer allocate(size_type _Count)
		{	// allocate array of _Count elements, ignore hint
		return (_Outer_traits::allocate(outer_allocator(),
			_Count));
		}

	pointer allocate(size_type _Count, const_void_pointer _Hint)
		{	// allocate array of _Count elements, with hint
		return (_Outer_traits::allocate(outer_allocator(),
			_Count, _Hint));
		}

	void deallocate(pointer _Ptr, size_type _Count)
		{	// deallocate object at _Ptr, with size
		return (_Outer_traits::deallocate(outer_allocator(),
			_Ptr, _Count));
		}

	size_type max_size() const
		{	// estimate maximum array size
		return (_Outer_traits::max_size(outer_allocator()));
		}

	template<class _Ty,
		class... _Types>
		void construct(_Ty *_Ptr, _Types&&... _Args)
		{	// construct with varying allocator styles
		_Scoped_construct(
			_Scoped_outermost_allocator<_Outer>::_Fn(0, *this),
			inner_allocator(),
			uses_allocator<_Ty, inner_allocator_type>(),
			is_constructible<_Ty, _Types..., inner_allocator_type>(),
			_Ptr, _STD forward<_Types>(_Args)...);
		}

	template<class _Ty>
		void destroy(_Ty *_Ptr)
		{	// destroy object at _Ptr
		_Outermost _Alval(_Scoped_outermost_allocator<_Outer>::_Fn(0, *this));
		_Outermost_traits::destroy(_Alval, _Ptr);
		}

		// CONSTRUCT A PAIR
	template<class _Ty1,
		class _Ty2,
		class _Tpl1,
		class _Tpl2>
		void construct(pair<_Ty1, _Ty2> *_Ptr, piecewise_construct_t,
			_Tpl1 _Val1, _Tpl2 _Val2)
		{	// construct pair from tuples
		_Scoped_construct_pair(inner_allocator(), _Ptr, _Val1, _Val2);
		}

	template<class _Ty1,
		class _Ty2>
		void construct(pair<_Ty1, _Ty2> *_Ptr)
		{	// construct pair from pointer to other pair
		this->construct(_Ptr, piecewise_construct,
			tuple<>(),
			tuple<>());
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			_Uy1&& _Val1, _Uy2&& _Val2)
		{	// construct pair from two movable values
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_STD forward<_Uy1>(_Val1)),
			forward_as_tuple(_STD forward<_Uy2>(_Val2)));
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			const pair<_Uy1, _Uy2>& _Other)
		{	// construct pair from copyable pair
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_Other.first),
			forward_as_tuple(_Other.second));
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			pair<_Uy1, _Uy2>&& _Other)
		{	// construct pair from movable pair
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_STD forward<_Uy1>(_Other.first)),
			forward_as_tuple(_STD forward<_Uy2>(_Other.second)));
		}
	};

template<class _Outer1,
	class _Outer2,
	class _Inner1,
	class... _Inner> inline
	bool operator==(
		const scoped_allocator_adaptor<_Outer1, _Inner1, _Inner...>& _Left,
		const scoped_allocator_adaptor<_Outer2, _Inner1, _Inner...>& _Right)
			_NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (_Left.outer_allocator() == _Right.outer_allocator()
			&& _Left.inner_allocator() == _Right.inner_allocator());
		}

template<class _Outer1,
	class _Outer2> inline
	bool operator==(
		const scoped_allocator_adaptor<_Outer1>& _Left,
		const scoped_allocator_adaptor<_Outer2>& _Right) _NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (_Left.outer_allocator() == _Right.outer_allocator());
		}

template<class _Outer1,
	class _Outer2,
	class... _Inner> inline
	bool operator!=(
		const scoped_allocator_adaptor<_Outer1, _Inner...>& _Left,
		const scoped_allocator_adaptor<_Outer2, _Inner...>& _Right) _NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (!(_Left == _Right));
		}

 #else /* _HAS_VARIADIC_TEMPLATES */
template<class _Outer,
	class _Inner0 = _Nil,
	_MAX_CLASS_LIST>
	class scoped_allocator_adaptor;

		// TEMPLATE STRUCT _Scoped_propagate_on_container_*
#define _SCOPED_PROPAGATE_0( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, \
		CLASS_NAME, MEMBER_NAME, X3, X4) \
template<class _Outer, \
	_MAX_CLASS_LIST> \
	struct CLASS_NAME; \
template<class _Outer> \
	struct CLASS_NAME<_Outer, _MAX_NIL_LIST> \
	{	/* determines scoped_allocator_adaptor<_Outer> */ \
		/* ::propagate_on_container_* */ \
	typedef typename allocator_traits<_Outer> \
		::MEMBER_NAME::type type; \
	};

#define _SCOPED_PROPAGATE_1X( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, \
		CLASS_NAME, MEMBER_NAME, X3, X4) \
template<class _Outer \
	_EX(C) LIST(_CLASS_TYPE)> \
	struct CLASS_NAME<_Outer, \
		LIST(_TYPE) _EX(C) PADDING_LIST(_NIL_PAD)> \
	{	/* determines scoped_allocator_adaptor<_Outer, _Inner...> */ \
		/* ::propagate_on_container_* */ \
	typedef typename _If< allocator_traits<_Outer>::MEMBER_NAME::value, \
		true_type, \
		CLASS_NAME<LIST(_TYPE)> >::type::type type; \
	};

#define _EXPAND_SCOPED_PROPAGATE_0X(CLASS_NAME, MEMBER_NAME) \
_VARIADIC_EXPAND_0(_SCOPED_PROPAGATE_0, CLASS_NAME, MEMBER_NAME, , ) \
_VARIADIC_EXPAND_1X(_SCOPED_PROPAGATE_1X, CLASS_NAME, MEMBER_NAME, , )

_EXPAND_SCOPED_PROPAGATE_0X(
	_Scoped_propagate_on_container_copy,
	propagate_on_container_copy_assignment)

_EXPAND_SCOPED_PROPAGATE_0X(
	_Scoped_propagate_on_container_move,
	propagate_on_container_move_assignment)

_EXPAND_SCOPED_PROPAGATE_0X(
	_Scoped_propagate_on_container_swap,
	propagate_on_container_swap)

#undef _SCOPED_PROPAGATE_0
#undef _SCOPED_PROPAGATE_1X
#undef _EXPAND_SCOPED_PROPAGATE_0X

		// TEMPLATE STRUCT _Scoped_outermost_allocator
template<class _Outer>
	struct _Scoped_outermost_allocator
	{	// chooses outermost x.outer_allocator() or x
	template<class _Xouter>
		static auto _Fn(int, _Xouter& _Alval)
			-> decltype(_Alval.outer_allocator())
		{	// returned nested allocator argument
		return (_Alval.outer_allocator());
		}

	template<class _Xouter>
		static auto _Fn(_Wrap_int, _Xouter& _Alval)
			-> _Xouter&
		{	// returned allocator argument
		return (_Alval);
		}

	static _Outer _Outer_obj;

	typedef typename remove_reference<
		decltype(_Fn<_Outer>(0, _Outer_obj))>::type type;
	};

		// TEMPLATE FUNCTION _Scoped_construct
#define _SCOPED_CONSTRUCT( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Outermost, \
	class _Inner, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE), \
	class _Dont_care> \
	void _Scoped_construct(_Outermost, _Inner, \
		false_type, _Dont_care, \
		_Ty *_Ptr _EX(C) LIST(_TYPE_REFREF_ARG)) \
	{	/* construct with optional arguments, no allocator */ \
	::new (_Ptr) _Ty(LIST(_FORWARD_ARG)); \
	} \
template<class _Outermost, \
	class _Inner, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE)> \
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval, \
		true_type, false_type, \
		_Ty *_Ptr _EX(C) LIST(_TYPE_REFREF_ARG)) \
	{	/* construct with optional arguments, leading allocator */ \
	allocator_traits<_Outermost>::construct(_Alval, _Ptr, \
		allocator_arg, _Inner_alval \
			_EX(C) LIST(_FORWARD_ARG)); \
	} \
template<class _Outermost, \
	class _Inner, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE)> \
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval, \
		true_type, true_type, \
		_Ty *_Ptr _EX(C) LIST(_TYPE_REFREF_ARG)) \
	{	/* construct with optional arguments, trailing allocator */ \
	allocator_traits<_Outermost>::construct(_Alval, _Ptr \
		_EX(C) LIST(_FORWARD_ARG), \
			_Inner_alval); \
	}

_VARIADIC_EXPAND_0X(_SCOPED_CONSTRUCT, , , , )
#undef _SCOPED_CONSTRUCT

		// TEMPLATE FUNCTION _Scoped_construct_tuple
#define _SCOPED_CONSTRUCT_TUPLE( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Alloc, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE), \
	class _Dont_care> \
	tuple<LIST(_TYPE)> \
		_Scoped_construct_tuple(_Alloc&, false_type, _Dont_care, \
			tuple<LIST(_TYPE)> _Val) \
	{	/* construct tuple from tuple argument, no allocator */ \
	return (_Val); \
	} \
template<class _Alloc, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE)> \
	tuple<allocator_arg_t, _Alloc& _EX(C) LIST(_TYPE)> \
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, false_type, \
			tuple<LIST(_TYPE)> _Val) \
	{	/* construct tuple from tuple argument, leading allocator */ \
	return (tuple_cat(tuple<allocator_arg_t, _Alloc&>( \
		_Tuple_alloc, _Alty), _Val)); \
	} \
template<class _Alloc, \
	class _Ty \
	_EX(C) LIST(_CLASS_TYPE)> \
	tuple<LIST(_TYPE) _EX(C) _Alloc&> \
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, true_type, \
			tuple<LIST(_TYPE)> _Val) \
	{	/* construct tuple from tuple argument, trailing allocator */ \
	return (tuple_cat(_Val, \
		tuple<_Alloc&>(_Alty))); \
	}

_VARIADIC_EXPAND_0X(_SCOPED_CONSTRUCT_TUPLE, , , , )
#undef _SCOPED_CONSTRUCT_TUPLE

		// TEMPLATE FUNCTION _Scoped_construct_pair
#define _SCOPED_CONSTRUCT_PAIR( \
	TEMPLATE_LIST1, PADDING_LIST1, LIST1, C1, \
	TEMPLATE_LIST2, PADDING_LIST2, LIST2, C2) \
template<class _Inner, \
	class _Ty1, \
	class _Ty2 \
	_EX(C1) LIST1(_CLASS_TYPE) \
	_EX(C2) LIST2(_CLASS_TYPEX)> \
	void _Scoped_construct_pair(_Inner _Inner_alval, \
		pair<_Ty1, _Ty2> *_Ptr, \
		tuple<LIST1(_TYPE)> _Val1, tuple<LIST2(_TYPEX)> _Val2) \
	{	/* construct pair from tuples */ \
	::new (_Ptr) pair<_Ty1, _Ty2>(piecewise_construct, \
		_Scoped_construct_tuple<_Inner, _Ty1 _EX(C1) LIST1(_TYPE)>( \
			_Inner_alval, \
			uses_allocator<_Ty1, _Inner>(), \
			is_constructible<_Ty1 _EX(C1) LIST1(_TYPE), _Inner>(), \
			_Val1), \
		_Scoped_construct_tuple<_Inner, _Ty2 _EX(C2) LIST2(_TYPEX)>( \
			_Inner_alval, \
			uses_allocator<_Ty2, _Inner>(), \
			is_constructible<_Ty2 _EX(C2) LIST2(_TYPEX), _Inner>(), \
			_Val2)); \
	}

_VARIADIC_EXPAND_0X_0X(_SCOPED_CONSTRUCT_PAIR)
#undef _SCOPED_CONSTRUCT_PAIR

		// TEMPLATE CLASS _Scoped_base
template<class _Outer,
	class = _Nil,
	_MAX_CLASS_LIST>
	struct _Scoped_base;

#define _SCOPED_BASE( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Outer, \
	class _Inner0 \
	_EX(C) LIST(_CLASS_TYPE)> \
	struct _Scoped_base<_Outer, _Inner0 _EX(C) \
		LIST(_TYPE), PADDING_LIST(_NIL_PAD)> \
	{	/* nest of allocators, arbitrary depth */ \
	typedef scoped_allocator_adaptor<_Outer, _Inner0 _EX(C) LIST(_TYPE)> \
		_Myadaptor; \
	typedef scoped_allocator_adaptor<_Inner0 _EX(C) LIST(_TYPE)> \
		inner_allocator_type; \
	inner_allocator_type _Inner_obj; \
	inner_allocator_type& _Get_inner_object( \
		_Myadaptor&) \
		{	/* return _Inner_obj as inner_object */ \
		return (_Inner_obj); \
		} \
	const inner_allocator_type& _Get_inner_object( \
		const _Myadaptor&) const \
		{	/* return _Inner_obj as inner_object */ \
		return (_Inner_obj); \
		} \
	_Scoped_base() \
		{	/* default construct */ \
		} \
	template<class _Other1, \
		class _Other2> \
		_Scoped_base(_Other1&& _Outer_arg, \
			_Other2&& _Inner_arg) \
		: _Inner_obj(_STD forward<_Other2>(_Inner_arg)) \
		{	/* construct from (outer, inner) */ \
		(_Outer&)*this = _STD forward<_Other1>(_Outer_arg); \
		} \
	template<class _Other> \
		void operator=( \
			scoped_allocator_adaptor<_Other, _Inner0 \
				_EX(C) LIST(_TYPE)>&& _Right) \
		{	/* move from adaptor<_Other, _Inner0, _Inner...> */ \
		(_Outer&)*this = _STD forward<_Other>(_Right); \
		_Inner_obj = _STD forward<inner_allocator_type>(_Right._Inner_obj); \
		} \
	template<class _Other> \
		void operator=( \
			const scoped_allocator_adaptor<_Other, _Inner0 \
				_EX(C) LIST(_TYPE)>& _Right) \
		{	/* assign from adaptor<_Other, _Inner0, _Inner...> */ \
		(_Outer&)*this = (_Other&)_Right; \
		_Inner_obj = _Right._Inner_obj; \
		} \
	_Myadaptor select_on_container_copy_construction() const \
		{	/* make new adaptor */ \
		return (_Myadaptor(allocator_traits<_Outer> \
			::select_on_container_copy_construction(*this), \
			_Inner_obj.select_on_container_copy_construction())); \
		} \
	};

_VARIADIC_EXPAND_0X(_SCOPED_BASE, , , , )
#undef _SCOPED_BASE

template<class _Outer>
	struct _Scoped_base<_Outer>
		: public _Outer
	{	// nest of allocators, one deep
	typedef scoped_allocator_adaptor<_Outer> _Myadaptor;
	typedef scoped_allocator_adaptor<_Outer> inner_allocator_type;

	inner_allocator_type& _Get_inner_object(
		_Myadaptor& _Self)
		{	// return self as inner_object
		return (_Self);
		}

	const inner_allocator_type& _Get_inner_object(
		const _Myadaptor& _Self) const
		{	// return self as inner_object
		return (_Self);
		}

	_Scoped_base()
		{	// default construct
		}

	template<class _Other1,
		class _Other2>
		_Scoped_base(_Other1&& _Outer_arg,
			_Other2&&)
		: _Outer(_STD forward<_Other1>(_Outer_arg))
		{	// construct from (outer, inner)
		}

	template<class _Other>
		void operator=(scoped_allocator_adaptor<_Other>&& _Right)
		{	// move from adaptor<_Other>
		(_Outer&)*this = _STD forward<_Other>((_Other&)_Right);
		}

	template<class _Other>
		void operator=(const scoped_allocator_adaptor<_Other>& _Right)
		{	// assign from adaptor<_Other>
		(_Outer&)*this = (_Other&)_Right;
		}

	_Myadaptor select_on_container_copy_construction() const
		{	// make new adaptor
		return (_Myadaptor(allocator_traits<_Outer>
			::select_on_container_copy_construction(*this)));
		}
	};

		// TEMPLATE CLASS scoped_allocator_adaptor
#define _SCOPED_ALLOCATOR_ADAPTOR( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Outer \
	_EX(C) LIST(_CLASS_TYPE)> \
	class scoped_allocator_adaptor<_Outer _EX(C) \
		LIST(_TYPE), PADDING_LIST(_NIL_PAD), _Nil> \
		: public _Scoped_base<_Outer _EX(C) LIST(_TYPE)> \
	{	/* nest of allocators */ \
	typedef _Scoped_base<_Outer _EX(C) LIST(_TYPE)> _Mybase; \
	typedef allocator_traits<_Outer> _Outer_traits; \
	typedef typename _Scoped_outermost_allocator<_Outer>::type _Outermost; \
	typedef allocator_traits<_Outermost> _Outermost_traits; \
public: \
	typedef _Outer outer_allocator_type; \
	typedef typename _Mybase::inner_allocator_type inner_allocator_type; \
	typedef typename _Outer_traits::value_type value_type; \
	typedef typename _Outer_traits::pointer pointer; \
	typedef typename _Outer_traits::const_pointer const_pointer; \
	typedef typename _Outer_traits::void_pointer void_pointer; \
	typedef typename _Outer_traits::const_void_pointer const_void_pointer; \
	typedef typename _Outer_traits::size_type size_type; \
	typedef typename _Outer_traits::difference_type difference_type; \
	template<class _Other> \
		struct rebind \
		{	/* converts X<value_type> to X<_Other> */ \
		typedef typename _Get_rebind_type<_Outer, _Other>::type \
			_Other_alloc; \
		typedef scoped_allocator_adaptor<_Other_alloc _EX(C) LIST(_TYPE)> \
			other; \
		}; \
	typedef typename \
		_Scoped_propagate_on_container_copy<_Outer _EX(C) LIST(_TYPE)>::type \
			propagate_on_container_copy_assignment; \
	typedef typename \
		_Scoped_propagate_on_container_move<_Outer _EX(C) LIST(_TYPE)>::type \
			propagate_on_container_move_assignment; \
	typedef typename \
		_Scoped_propagate_on_container_swap<_Outer _EX(C) LIST(_TYPE)>::type \
			propagate_on_container_swap; \
	outer_allocator_type& outer_allocator() _NOEXCEPT \
		{	/* get reference to outer allocator */ \
		return (reinterpret_cast<_Outer&>(*this)); \
		} \
	const outer_allocator_type& outer_allocator() const _NOEXCEPT \
		{	/* get reference to outer allocator */ \
		return (reinterpret_cast<const _Outer&>(*this)); \
		} \
	inner_allocator_type& inner_allocator() _NOEXCEPT \
		{	/* get reference to inner allocator */ \
		return (const_cast<inner_allocator_type&>( \
			this->_Get_inner_object(*this))); \
		} \
	const inner_allocator_type& inner_allocator() const _NOEXCEPT \
		{	/* get reference to inner allocator */ \
		return (this->_Get_inner_object(*this)); \
		} \
	scoped_allocator_adaptor() \
		{	/* default construct */ \
		} \
	scoped_allocator_adaptor(const scoped_allocator_adaptor& _Right) \
		_NOEXCEPT \
		: _Mybase(_Right.outer_allocator(), \
			_Right.inner_allocator()) \
		{	/* construct from _Right */ \
		} \
	template<class _Other> \
		scoped_allocator_adaptor(_Other&& _Other_arg \
			_EX(C) LIST(_CONST_TYPE_REF_ARG)) _NOEXCEPT \
		: _Mybase(_STD forward<_Other>(_Other_arg), \
			_STD forward<inner_allocator_type>( \
				inner_allocator_type(LIST(_ARG)))) \
		{	/* construct from (_Other, _Inner...) */ \
		} \
	template<class _Other> \
		scoped_allocator_adaptor(const scoped_allocator_adaptor<_Other \
			_EX(C) LIST(_TYPE)>& _Right) _NOEXCEPT \
		: _Mybase(_Right.outer_allocator(), \
			_Right.inner_allocator()) \
		{	/* construct from const adaptor<_Other, _Inner...>& */ \
		} \
	template<class _Other> \
		scoped_allocator_adaptor(scoped_allocator_adaptor<_Other \
			_EX(C) LIST(_TYPE)>&& _Right) _NOEXCEPT \
		: _Mybase(_STD forward<_Other>(_Right.outer_allocator()), \
			_Right.inner_allocator()) \
		{	/* construct from adaptor<_Other, _Inner...>&& */ \
		} \
	template<class _Other> \
		scoped_allocator_adaptor& operator=( \
			scoped_allocator_adaptor<_Other _EX(C) LIST(_TYPE)>&& _Right) \
		{	/* assign from adaptor<_Other _EX(C) LIST(_TYPE)>&& */ \
		_Mybase::operator=(_STD forward<_Other>(_Right)); \
		return (*this); \
		} \
	template<class _Other> \
		scoped_allocator_adaptor& operator=( \
			const scoped_allocator_adaptor<_Other _EX(C) LIST(_TYPE)>& \
				_Right) \
		{	/* assign from adaptor<_Other, _Inner...>& */ \
		_Mybase::operator=(_Right); \
		return (*this); \
		} \
	pointer allocate(size_type _Count) \
		{	/* allocate array of _Count elements, ignore hint */ \
		return (_Outer_traits::allocate(outer_allocator(), \
			_Count)); \
		} \
	pointer allocate(size_type _Count, const_void_pointer _Hint) \
		{	/* allocate array of _Count elements, with hint */ \
		return (_Outer_traits::allocate(outer_allocator(), \
			_Count, _Hint)); \
		} \
	void deallocate(pointer _Ptr, size_type _Count) \
		{	/* deallocate object at _Ptr, with size */ \
		return (_Outer_traits::deallocate(outer_allocator(), \
			_Ptr, _Count)); \
		} \
	size_type max_size() const \
		{	/* estimate maximum array size */ \
		return (_Outer_traits::max_size(outer_allocator())); \
		} \
_VARIADIC_EXPAND_ALT_0X(_SCOPED_ALLOCATOR_ADAPTOR_CONSTRUCT, , , , ) \
	template<class _Ty> \
		void destroy(_Ty *_Ptr) \
		{	/* destroy object at _Ptr */ \
		_Outermost _Alval(_Scoped_outermost_allocator<_Outer> \
			::_Fn(0, *this)); \
		_Outermost_traits::destroy(_Alval, _Ptr); \
		} \
		/* CONSTRUCT A PAIR */ \
	template<class _Ty1, \
		class _Ty2, \
		class _Tpl1, \
		class _Tpl2> \
		void construct(pair<_Ty1, _Ty2> *_Ptr, piecewise_construct_t, \
			_Tpl1 _Val1, _Tpl2 _Val2) \
		{	/* construct pair from tuples */ \
		_Scoped_construct_pair(inner_allocator(), _Ptr, _Val1, _Val2); \
		} \
	template<class _Ty1, \
		class _Ty2> \
		void construct(pair<_Ty1, _Ty2> *_Ptr) \
		{	/* construct pair from pointer to other pair */ \
		this->construct(_Ptr, piecewise_construct, \
			tuple<>(), \
			tuple<>()); \
		} \
	template<class _Ty1, \
		class _Ty2, \
		class _Uy1, \
		class _Uy2> \
		void construct(pair<_Ty1, _Ty2> *_Ptr, \
			_Uy1&& _Val1, _Uy2&& _Val2) \
		{	/* construct pair from two movable values */ \
		this->construct(_Ptr, piecewise_construct, \
			forward_as_tuple(_STD forward<_Uy1>(_Val1)), \
			forward_as_tuple(_STD forward<_Uy2>(_Val2))); \
		} \
	template<class _Ty1, \
		class _Ty2, \
		class _Uy1, \
		class _Uy2> \
		void construct(pair<_Ty1, _Ty2> *_Ptr, \
			const pair<_Uy1, _Uy2>& _Other) \
		{	/* construct pair from copyable pair */ \
		this->construct(_Ptr, piecewise_construct, \
			forward_as_tuple(_Other.first), \
			forward_as_tuple(_Other.second)); \
		} \
	template<class _Ty1, \
		class _Ty2, \
		class _Uy1, \
		class _Uy2> \
		void construct(pair<_Ty1, _Ty2> *_Ptr, \
			pair<_Uy1, _Uy2>&& _Other) \
		{	/* construct pair from movable pair */ \
		this->construct(_Ptr, piecewise_construct, \
			forward_as_tuple(_STD forward<_Uy1>(_Other.first)), \
			forward_as_tuple(_STD forward<_Uy2>(_Other.second))); \
		} \
	};

#define _SCOPED_ALLOCATOR_ADAPTOR_CONSTRUCT( \
	TEMPLATE_LIST2, PADDING_LIST2, LIST2, C2, X1, X2, X3, X4) \
	template<class _Ty \
		_EX(C2) LIST2(_CLASS_TYPEX)> \
		void construct(_Ty *_Ptr _EX(C2) LIST2(_TYPEX_REFREF_ARG)) \
		{	/* construct with varying allocator styles */ \
		_Scoped_construct( \
			_Scoped_outermost_allocator<_Outer>::_Fn(0, *this), \
			inner_allocator(), \
			uses_allocator<_Ty, inner_allocator_type>(), \
			is_constructible<_Ty _EX(C2) LIST2(_TYPEX), \
				inner_allocator_type>(), \
			_Ptr _EX(C2) LIST2(_FORWARD_ARGX)); \
		}

_VARIADIC_EXPAND_0X(_SCOPED_ALLOCATOR_ADAPTOR, , , , )

#undef _SCOPED_ALLOCATOR_ADAPTOR_CONSTRUCT
#undef _SCOPED_ALLOCATOR_ADAPTOR

#define _SCOPED_ALLOCATOR_COMPARE_EQUAL( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Outer1, \
	class _Outer2 \
	_EX(C) LIST(_CLASS_TYPE)> inline \
	bool operator==( \
		const scoped_allocator_adaptor<_Outer1 _EX(C) LIST(_TYPE)>& _Left, \
		const scoped_allocator_adaptor<_Outer2 _EX(C) LIST(_TYPE)>& _Right) \
			_NOEXCEPT \
		{	/* compare scoped_allocator_adaptors for equality */ \
		return (_Left.outer_allocator() == _Right.outer_allocator() \
			&& _Left.inner_allocator() == _Right.inner_allocator()); \
		}

_VARIADIC_EXPAND_1X(_SCOPED_ALLOCATOR_COMPARE_EQUAL, , , , )
#undef _SCOPED_ALLOCATOR_COMPARE_EQUAL

template<class _Outer1,
	class _Outer2> inline
	bool operator==(
		const scoped_allocator_adaptor<_Outer1>& _Left,
		const scoped_allocator_adaptor<_Outer2>& _Right) _NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (_Left.outer_allocator() == _Right.outer_allocator());
		}

#define _SCOPED_ALLOCATOR_COMPARE_NOT_EQUAL( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
template<class _Outer1, \
	class _Outer2 \
	_EX(C) LIST(_CLASS_TYPE)> inline \
	bool operator!=( \
		const scoped_allocator_adaptor<_Outer1 _EX(C) LIST(_TYPE)>& _Left, \
		const scoped_allocator_adaptor<_Outer2 _EX(C) LIST(_TYPE)>& _Right) \
			_NOEXCEPT \
		{	/* compare scoped_allocator_adaptors for equality */ \
		return (!(_Left == _Right)); \
		}

_VARIADIC_EXPAND_0X(_SCOPED_ALLOCATOR_COMPARE_NOT_EQUAL, , , , )
#undef _SCOPED_ALLOCATOR_COMPARE_NOT_EQUAL
 #endif /* _HAS_VARIADIC_TEMPLATES */
_STD_END
#endif /* _SCOPED_ALLOCATOR_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:1422 */
